#include "dht11.h"
#include "bflb_gpio.h"
#include "bflb_mtimer.h"
#define CONFIG_LOG_NCOLOR 1
#include "log.h"


#define DHT_read_set(gpio,dev)  \
    do                          \
    {                           \
        bflb_gpio_init(gpio,    \
        dev->pin,               \
        GPIO_INPUT|GPIO_PULLUP|GPIO_SMT_EN|GPIO_DRV_0); \
    }while (0)

#define DHT_write_set(gpio,dev)     \
    do                              \
    {                               \
        bflb_gpio_init(gpio,        \
            dev->pin,               \
            GPIO_OUTPUT|GPIO_PULLUP|GPIO_SMT_EN|GPIO_DRV_0);\
    } while (0);


void dht_init(struct bflb_device_s* gpio, DHT11_t* dev, uint8_t pin) {

    dev->status = DHT_STATUS_INIT;
    dev->pin = pin;
    DHT_write_set(gpio, dev);
    bflb_gpio_set(gpio, dev->pin);
    //等待1s越过不稳定状态
    bflb_mtimer_delay_ms(1000);
    dev->status = DHT_STATUS_READY;
}

uint8_t dht_check(struct bflb_device_s* gpio, DHT11_t* dev) {
    DHT_read_set(gpio, dev);
    uint8_t retry = 0;
    //dht会拉低电平80us
    while (!bflb_gpio_read(gpio, dev->pin) && retry < 100) {
        retry++;
        bflb_mtimer_delay_us(1);
    }
    if (retry >= 100) {
        return 0;
    }
    retry = 0;
    //再次拉高80us
    while (bflb_gpio_read(gpio, dev->pin) && retry < 100) {
        retry++;
        bflb_mtimer_delay_us(1);
    }
    if (retry >= 100) {
        return 0;
    }
    else {
        return 1;
    }
}

static uint8_t dht_read_bit(struct bflb_device_s* gpio, DHT11_t* dev) {
    uint8_t retry = 0;
    //54us低电平
    while (!bflb_gpio_read(gpio, dev->pin) && retry < 70) {
        retry++;
        bflb_mtimer_delay_us(1);
    }
    retry = 0;
    //高电平23~27us是0，高电平68~71us是1
    //延迟30us
    bflb_mtimer_delay_us(35);
    uint8_t ret = bflb_gpio_read(gpio, dev->pin);
    //等待高电平结束
    if (ret) {
        while (bflb_gpio_read(gpio, dev->pin) && retry < 50) {
            retry++;
            bflb_mtimer_delay_us(1);
        }
    }

    return ret;
}

static int8_t dht_read_byte(struct bflb_device_s* gpio, DHT11_t* dev) {
    int8_t ret = 0;
    for (int i = 0; i < 8; i++) {
        ret <<= 1;
        ret |= dht_read_bit(gpio, dev);
    }
    return ret;
}
DHT_CODE dht_read_data(struct bflb_device_s* gpio, DHT11_t* dev, int16_t* temp, uint16_t* humidity) {
    //检查dev状态
    if (dev->status != DHT_STATUS_READY) {
        return dev->status;
    }

    dev->status = DHT_STATUS_READING;
    //空闲高电平
    DHT_write_set(gpio, dev);
    bflb_gpio_set(gpio, dev->pin);
    bflb_mtimer_delay_us(60);

    //拉低电平20ms上,发送开始信号
    bflb_gpio_reset(gpio, dev->pin);
    bflb_mtimer_delay_ms(20);

    // //拉高电平延迟10 ~ 20us，结束开始信号
    bflb_gpio_set(gpio, dev->pin);
    bflb_mtimer_delay_us(13);

    DHT_CODE ret = DHT_CODE_SUCCEED;
    uint8_t buf[5] = { 0 };
    //检测设备
    if (dht_check(gpio, dev)) {
        for (int i = 0;i < 5;i++) {
            buf[i] = dht_read_byte(gpio, dev);
        }
        uint16_t sum = buf[0] + buf[1] + buf[2] + buf[3];

        if (sum == buf[4]) {
            *humidity = buf[0] * 10 + buf[1];
            //温度小数数据第8位为1代表负数，低7位代表实际数值
            *temp = buf[2] * 10 + (buf[3] & 0x7f);
            if ((buf[3] & 0x80) == 0x80) {
                *temp = -*temp;
            }
        }
        else {
            LOG_E("%d,%d,%d,%d,sum: %d,buf[4]: %d\n", buf[0], buf[1], buf[2], buf[3], sum, buf[4]);
            ret = DHT_CODE_DATA_ERR;
        }
    }
    else {
        ret = DHT_CODE_NOACK;
        LOG_E("设备未回复\n");
    }

    dev->status = DHT_STATUS_READY;
    return ret;
}